package workers;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.Collections;

import org.farng.mp3.MP3File;
import org.farng.mp3.TagException;
import org.farng.mp3.id3.AbstractID3v2;
import org.farng.mp3.id3.ID3v1;
import org.farng.mp3.id3.ID3v1_1;
import org.farng.mp3.id3.ID3v2_2;

import application.Server;

public class Busquedas {
	
	public static final String BUSCAR_POR_NOMBRE_ARCHIVO = "NOMBRE";
	public static final String BUSCAR_POR_FORMATO_ARCHIVO = "FORMATO";
	public static final String BUSCAR_POR_NOMBRE_ARTISTA = "ARTISTA";
	public static final String BUSCAR_POR_NOMBRE_CANCION = "CANCION";
	public static final String BUSCAR_POR_NOMBRE_ALBUM = "ALBUM";
	public static final String BUSCAR_POR_ANO = "AGNO";
	public static final String BUSCAR_POR_TAMANO = "TAMANO";
	
	public static final float TAMANO_RANKING_1 = 0.10f;
	public static final float TAMANO_RANKING_2 = 0.20f;
	public static final float TAMANO_RANKING_3 = 0.30f;
	public static final float TAMANO_RANKING_4 = 0.40f;
	public static final float TAMANO_RANKING_5 = 0.50f;
	
	Logger logger = Logger.getLogger( Server.loggerName );
	
	class TamanoComparator implements Comparator {

		  public int compare(Object o1, Object o2) {
		    File u1 = (File) o1;
		    File u2 = (File) o2;
		    
		    return Integer.parseInt(String.valueOf((u1.length() - u2.length())));
		  }

		  public boolean equals(Object o) {
		    return this == o;
		  }
		}	
	
	/**
	 * 
	 * @param tipo
	 * @param root
	 * @param key
	 * @return
	 */
	public String buscarArchivos(String tipo, File root, String key)
	{
		String list = "";
		String cadena = "";
		List listList = new ArrayList();
		float ranking = 0.0f;
		long media = 0;
		int cantidad = 0;
		try {		
			File temp;
			File rootFile = new File(root.getAbsolutePath());
			File listFiles[] = rootFile.listFiles();
			ranking = TAMANO_RANKING_5;
			
			/*Ordenamiento Burbuja*/
			 for (int i = 0; i <= listFiles.length - 2; i++) {
			 	 for (int j = i + 1; j <= listFiles.length - 1; j++) {
		 	  	 	 if (listFiles[i].length() > listFiles[j].length()) 
		 	  	 	 {
				 	 	temp = listFiles[i];
				 	 	listFiles[i] = listFiles[j];
				 	 	listFiles[j] = temp;
		 	  	 	 }
				 }	 
			 }					
			/*fin ordenamiento*/
			 
			if (tipo.equals(BUSCAR_POR_TAMANO))
			{								
				List<File> lista = new ArrayList<File>();  
			    for(int i = 0; i < listFiles.length; i++)
			    { 
			    	if (listFiles[i].getName().endsWith(".mp3"))
			    	{
			    		lista.add(listFiles[i]);
			    	}
			    } 				
			    //Collections.sort(lista, new TamanoComparator());
			    int fSize = Integer.parseInt(key);
			    long dif = 999999999999999999L;		
		    	if (lista.size() > 0 && fSize < ((File) lista.get(0)).length())
		    	{
		    		if (obtenerRanking(fSize, ((File) lista.get(0)).length(), ranking))
		    			return ((File) lista.get(0)).getName() + "_" + ((File) lista.get(0)).length() + "@";
		    	}
		    	if (lista.size() > 0 && fSize > ((File) lista.get(lista.size() - 1)).length())
		    	{
		    		if (obtenerRanking(fSize, ((File) lista.get(lista.size() - 1)).length(), ranking))
		    			return ((File) lista.get(lista.size() - 1)).getName() + "_" + ((File) lista.get(0)).length() + "@";
		    	}		    	
			    for (int i = 0; i < lista.size(); i++)
			    {
			    	File fa = (File) lista.get(i);
			    	if ((i + 1) < lista.size())
			    	{
			    		File fb = (File) lista.get(i + 1);
			    		//System.out.println("fSize: " + fSize + " - fa: " + fa.length() + " - fb: " + fb.length());
			    		if (fSize >= fa.length() && fSize <= fb.length())
			    		{
			    			long difa = fSize - fa.length(); 
			    			long difb = fb.length() - fSize;	
			    			//System.out.println("difa: " + difa + " <= difb: " + difb + " - dif: " + dif);
			    			if (difa <= difb && difa < dif)
			    			{
			    				dif = difa;
			    				if (obtenerRanking(fSize, fa.length(), ranking))
			    					list = fa.getName() + "_" + fa.length() + "@";
			    			}
			    			else if (difb <= difa && difb < dif)
			    			{
			    				dif = difb;
			    				if (obtenerRanking(fSize, fa.length(), ranking))
			    					list = fb.getName() + "_" + fa.length() + "@";
			    			}
			    			
			    		}
			    	}
			    }
			    //System.out.println(list);
			}				
			else
			{
				Pattern p = null;	
				String patronBusqueda = key;
				if (patronBusqueda.contains("*"))
				{
					patronBusqueda = patronBusqueda.replace("*", "[a-zA-Z0-9]+");
				}				
				//logger.fine("patronBusqueda: " + patronBusqueda );
				p = Pattern.compile(".*(" + patronBusqueda + ").*", Pattern.CASE_INSENSITIVE + Pattern.DOTALL);				
				for (int i = 0; i < listFiles.length; i++)
				{
					if((tipo.equals(BUSCAR_POR_NOMBRE_ARTISTA) || tipo.equals(BUSCAR_POR_NOMBRE_CANCION) 
							|| tipo.equals(BUSCAR_POR_NOMBRE_ALBUM) || tipo.equals(BUSCAR_POR_ANO))
							&& listFiles[i].getName().endsWith(".mp3"))
					{
						RandomAccessFile raf = new RandomAccessFile(listFiles[i], "r");					 					    	
					    
						MP3File mp3file = new MP3File(listFiles[i]);
						
						ID3v1 id3v1 = mp3file.getID3v1Tag();
						ID3v1_1 id3v1_1 = new ID3v1_1(raf);	
						AbstractID3v2 id3v2 = mp3file.getID3v2Tag();
												
						if (tipo.equals(BUSCAR_POR_NOMBRE_ARTISTA))
						{
							cadena = id3v1.getArtist();
							if (cadena == null)
							{
								cadena = id3v1_1.getArtist();								
							}
							if (cadena == null)
							{
								cadena = id3v2.getLeadArtist();
							}
							
							Matcher mm = p.matcher(cadena);
							if (mm.matches())
							{
								list +=  listFiles[i].getName() + "@";
								//logger.fine("id3v1_1 - Artista: " + id3v1_1.getArtist());
								System.out.println("id3v1 - getArtist: " + id3v1.getArtist());
								System.out.println("id3v1_1 - getArtist: " + id3v1_1.getArtist());								
								System.out.println("id3v2 - getLeadArtist: " + id3v2.getLeadArtist());
							}							
						}
						else if (tipo.equals(BUSCAR_POR_NOMBRE_CANCION))
						{
							cadena = id3v1.getSongTitle();
							if (cadena == null)
							{
								cadena = id3v1_1.getSongTitle();								
							}
							if (cadena == null)
							{
								cadena = id3v2.getSongTitle();
							}
							
							Matcher mm = p.matcher(cadena);
							if (mm.matches())
							{
								list +=  listFiles[i].getName() + "@";
								//logger.fine("id3v1_1 - Artista: " + id3v1.getSongTitle());
								System.out.println("id3v1 - getSongTitle: " + id3v1.getSongTitle());
								System.out.println("id3v1_1 - getSongTitle: " + id3v1_1.getSongTitle());								
								System.out.println("id3v2 - getSongTitle: " + id3v2.getSongTitle());								
							}															
						}
						else if (tipo.equals(BUSCAR_POR_NOMBRE_ALBUM))
						{
							cadena = id3v1.getAlbum();
							if (cadena == null)
							{
								cadena = id3v1_1.getAlbum();								
							}
							if (cadena == null)
							{
								cadena = id3v2.getAlbumTitle();
							}
							
							Matcher mm = p.matcher(cadena);
							if (mm.matches())
							{
								list +=  listFiles[i].getName() + "@";
								//logger.fine("id3v1_1 - Artista: " + id3v1.getSongTitle());
								System.out.println("id3v1 - getAlbum: " + id3v1.getAlbum());
								System.out.println("id3v1_1 - getAlbum: " + id3v1_1.getAlbum());								
								System.out.println("id3v2 - getAlbumTitle: " + id3v2.getAlbumTitle());																
							}																				
						}
						else if (tipo.equals(BUSCAR_POR_ANO))
						{
							cadena = id3v1.getYear();
							if (cadena == null)
							{
								cadena = id3v1_1.getYear();								
							}
							if (cadena == null)
							{
								cadena = id3v2.getYearReleased();
							}
							
							Matcher mm = p.matcher(cadena);
							if (mm.matches())
							{
								list +=  listFiles[i].getName() + "@";
								//logger.fine("id3v1_1 - Artista: " + id3v1.getSongTitle());
								System.out.println("id3v1 - getYear: " + id3v1.getYear());
								System.out.println("id3v1_1 - getYear: " + id3v1_1.getYear());								
								System.out.println("id3v2 - getYearReleased: " + id3v2.getYearReleased());																
							}																				
						}						
					}
					else if (tipo.equals(BUSCAR_POR_NOMBRE_ARCHIVO))
					{
						Matcher mm = p.matcher(listFiles[i].getName());
						if (mm.matches())
						{
							list +=  listFiles[i].getName() + "@";
							listList.add(listFiles[i]);
							media += listFiles[i].length();							
							cantidad++;
						}																									
					}
					else if(tipo.equals(BUSCAR_POR_FORMATO_ARCHIVO))
					{
						p = Pattern.compile(".*(" + patronBusqueda + ")", Pattern.CASE_INSENSITIVE + Pattern.DOTALL);
						Matcher mm = p.matcher(listFiles[i].getName());
						if (mm.matches())
						{
							list +=  listFiles[i].getName() + "@";
							listList.add(listFiles[i]);
							media += listFiles[i].length();							
							cantidad++;							
						}					
					}
					
					else
					{
						logger.fine("Busqueda no permitida: " + tipo);
					}
				}
				if (tipo.equals(BUSCAR_POR_NOMBRE_ARCHIVO) || tipo.equals(BUSCAR_POR_FORMATO_ARCHIVO))
				{
					try
					{
						long difA = 0;
						long difB = 0;
						if (cantidad > 0 )
							media = media / cantidad;
						
						System.out.println("Media: " + media); //****1
						difA = media - ((File) listList.get(0)).length();
						difB = ((File) listList.get(listList.size()-1)).length() - media;//****2
						
						
						//File tmpFiles[] =  new File[listList.size()-1];
						
						/*Ordenamiento Burbuja*/
						 for (int i = 0; i <= listFiles.length - 2; i++) {
						 	 for (int j = i + 1; j <= listFiles.length - 1; j++) {
						 		 long a = listFiles[i].length() - media;
						 		 long b = listFiles[j].length() - media;
						 		 a = a < 0 ? a*-1 : a;
						 		 b = b < 0 ? b*-1 : b;
					 	  	 	 if (a > b) 
					 	  	 	 {
							 	 	temp = listFiles[i];
							 	 	listFiles[i] = listFiles[j];
							 	 	listFiles[j] = temp;							 	 	
					 	  	 	 }					 	  	 	 
							 }	 
						 }											 
						/*fin ordenamiento*/
						 
						 list = "";
						 for (int i = 0; i <= listFiles.length - 1; i++) 
						 {
							 list += listFiles[i].getName() + "@";
							 System.out.println(listFiles[i].getName() + " :: " + listFiles[i].length() + " :: " 
									 + ((listFiles[i].length() - media) < 0 ?  (listFiles[i].length() - media)*-1 : (listFiles[i].length() - media)));							 
						 }						 
						
					} 
					catch (Exception e)
					{
						e.printStackTrace();
					}
				}
			}
			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (TagException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return list;
	}

	public boolean obtenerRanking(int tamanoA, long tamanoB, float ranking)
	{
		boolean resultado = false;
		float valor = tamanoA * ranking; 
		long dif = (tamanoA - tamanoB);
		dif = dif < 0 ? dif * -1 : dif;
		
		if (dif <= valor)
			resultado = true;
			
		System.out.println("Ranking " + ranking + ": " + resultado);
		
		return resultado;
	}
	

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Busquedas b = new Busquedas();
		System.out.println(b.buscarArchivos(BUSCAR_POR_FORMATO_ARCHIVO, new File("C:\\tmp\\Musica\\04LUIS SILVA"), ".mp*"));
	}

}
